package com.cjm.thread.zhonjianjian;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class Samphere {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(10);
        for (int i = 0; i < 100; i++) {
            int x = i;
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    doSomthing(semaphore, x);
                }
            });
            t.start();
        }
    }

    /**
     * 但是如果场景再复杂一点 比如dosomthing是一个异步方法， 前面这段代码的效果就会大打折扣了， 如果
     * dosomthing的分支非常多， 或者遇到异步调用等复杂情况下， 归还许可将变得非常复杂；
     * 因为在使用信号量时， 如果多次调用release， 应用程序实际的并发数量会超过设置的许可值，
     * 所以避免重复调用release方法显得非常关键
     * @param semaphore
     * @param i
     */
    private static void doSomthing(Semaphore semaphore, int i) {
        boolean acquired = false;
        try {
            // 这种方法是尝试获取一个信号， 如果当前没有剩余的许可， 过了指定等待时间之会返回false， 表示未获取许可
            acquired = semaphore.tryAcquire(3000, TimeUnit.MICROSECONDS);
            if (acquired) {
                System.err.println("执行业务逻辑, i = " + i);
            } else {
                System.err.println("信号量未获取执行的逻辑, i = " + i);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            if (acquired) {
                // 归还许可， 该方法必须在tryAcquire方法返回true时调用， 不然会发生“许可超发”
                semaphore.release();
            }
        }
    }
}
